/**
 *******************************************************************************
 * @FileName  : track.h
 * @Author    : GaoQiu
 * @CreateDate: 2020-02-18
 * @Copyright : Copyright(C) GaoQiu
 *              All Rights Reserved.
 *******************************************************************************
 *
 * The information contained herein is confidential and proprietary property of
 * GaoQiu and is available under the terms of Commercial License Agreement
 * between GaoQiu and the licensee in separate contract or the terms described
 * here-in.
 *
 * This heading MUST NOT be removed from this file.
 *
 * Licensees are granted free, non-transferable use of the information in this
 * file under Mutual Non-Disclosure Agreement. NO WARRENTY of ANY KIND is provided.
 *
 *******************************************************************************
 */

#ifndef TRACK_H_
#define TRACK_H_

#include <stdarg.h>
#include "soft_uart.h"
#include "component/usb/usb_api.h"

#include "platform/platform.h"
#include "bsp/bsp.h"

/*! Track debug system config. (1: UART; 3:USB) */
#define TRACK_MODE_NONE               0
#define TRACK_MODE_UART               1  /** Hardware UART */
#define TRACK_MODE_SUART              2  /** Software UART: !!!!WARN - BLE timing error. */
#define TRACK_MODE_USB                3  /** USB  */

#ifndef TRACK_MODE
#define TRACK_MODE                    TRACK_MODE_NONE
#endif

/*! Timing debug system enable/disable. */
#ifndef TIMING_TRACK_EN
#define TIMING_TRACK_EN               0
#endif

/*! Software UART Track config. */
#if TRACK_MODE == TRACK_MODE_SUART
#define TRACK_PIN                     GPIO_PD7
#define TRACK_BAUDRATE                1000000
#endif

/*! Hardware UART Track config. */
#if TRACK_MODE == TRACK_MODE_UART
#ifdef TLSR8258_DK48
	#define TRACK_PIN                 GPIO_PB1
#else
	#define TRACK_PIN                 GPIO_PD7
#endif
	#define TRACK_BAUDRATE            1000000
#endif

#if TRACK_MODE != TRACK_MODE_NONE
#define TRACK_INIT()                  TrackInit()
#define TRACK_START()                 TrackStart()
#define write                         TrackPrint
#else
#define TRACK_INIT()
#define TRACK_START()
#define write
#endif

#if TRACK_MODE
	#define COM_TRACK_EN       1
	#define DRIV_TRACK_EN      1
	#define LL_TRACK_EN        1
	#define ENC_TRACK_EN       0
	#define HCI_TRACK_EN       1
	#define HCI_H5_TRACK_EN    1
	#define HCI_SLIP_TRACK_EN  1
    #define HCI_TR_TRACK_EN    0
    #define DM_TRACK_EN        0
	#define L2C_TRACK_EN       0
	#define ATT_TRACK_EN       0
	#define GATT_TRACK_EN      1
	#define SMP_TRACK_EN       1
	#define SDP_TRACK_EN       1
	#define APP_TRACK_EN       1
	#define USB_TRACK_EN       0
    #define MEM_TRACK_EN       0
#else
	#define COM_TRACK_EN       0
	#define DRIV_TRACK_EN      0
	#define LL_TRACK_EN        0
	#define ENC_TRACK_EN       0
	#define HCI_TRACK_EN       0
	#define HCI_TR_TRACK_EN    0
	#define HCI_H5_TRACK_EN    0
	#define HCI_SLIP_TRACK_EN  0
    #define HCI_TR_TRACK_EN    0
    #define DM_TRACK_EN        0
	#define L2C_TRACK_EN       0
	#define ATT_TRACK_EN       0
	#define GATT_TRACK_EN      0
	#define SMP_TRACK_EN       0
	#define SDP_TRACK_EN       0
	#define APP_TRACK_EN       0
	#define USB_TRACK_EN       0
    #define MEM_TRACK_EN       0
#endif


#define TRACK_COLOR_EN           	0

#define LOG_COLOR           "\033[0;%dm"
#define LOG_BOLD            "\033[1;%dm"
#define LOG_RESET_COLOR     "\033[0m"

#if TRACK_COLOR_EN
	/* ! The color for terminal (foreground)
	#define BLACK    30
	#define RED      31
	#define GREEN    32
	#define YELLOW   33
	#define BLUE     34
	#define PURPLE   35
	#define CYAN     36
	#define WHITE    37
	*/

	#define TRACK_COLOR_START(c)          write("\033["#c"m")
	#define TRACK_COLOR_END()             write("\033[0m")
#else
	#define TRACK_COLOR_START(c)
	#define TRACK_COLOR_END()
#endif

#if COM_TRACK_EN
	#define TRACK(format, ...)             write(format, ##__VA_ARGS__)
	#define TRACK_ERR(format, ...)         write("[E] "format, ##__VA_ARGS__)
	#define TRACK_INFO(format, ...)        write("[I] "format, ##__VA_ARGS__)
	#define TRACK_WRN(format, ...)         write("[W] "format, ##__VA_ARGS__)
#else
	#define TRACK(format, ...)
	#define TRACK_ERR(format, ...)
	#define TRACK_INFO(format, ...)
	#define TRACK_WRN(format, ...)
#endif

#if DRIV_TRACK_EN
	#define DRIV_TRACK_ERR(format, ...)    write("[E][DRV] "format, ##__VA_ARGS__)
	#define DRIV_TRACK_INFO(format, ...)   write("[I][DRV] "format, ##__VA_ARGS__)
	#define DRIV_TRACK_WRN(format, ...)    write("[W][DRV] "format, ##__VA_ARGS__)
#else
	#define DRIV_TRACK_ERR(format, ...)
	#define DRIV_TRACK_INFO(format, ...)
	#define DRIV_TRACK_WRN(format, ...)
#endif

#if LL_TRACK_EN
	#define LL_TRACK_ERR(format, ...)      write("[E][LL_] "format, ##__VA_ARGS__)
	#define LL_TRACK_INFO(format, ...)     write("[I][LL_] "format, ##__VA_ARGS__)
	#define LL_TRACK_WRN(format, ...)      write("[W][LL_] "format, ##__VA_ARGS__)
	#define LL_TRACK_DATA(pdata, len)      TRACK_DATA(pdata, len)
#else
	#define LL_TRACK_ERR(format, ...)
	#define LL_TRACK_INFO(format, ...)
	#define LL_TRACK_WRN(format, ...)
	#define LL_TRACK_DATA(pdata, len)
#endif

#if ENC_TRACK_EN
	#define ENC_TRACK_ERR(format, ...)      write("[E][ENC] "format, ##__VA_ARGS__)
	#define ENC_TRACK_INFO(format, ...)     write("[I][ENC] "format, ##__VA_ARGS__)
	#define ENC_TRACK_WRN(format, ...)      write("[W][ENC] "format, ##__VA_ARGS__)
	#define ENC_TRACK_DATA(pdata, len)      TRACK_DATA(pdata, len)
#else
	#define ENC_TRACK_ERR(format, ...)
	#define ENC_TRACK_INFO(format, ...)
	#define ENC_TRACK_WRN(format, ...)
	#define ENC_TRACK_DATA(pdata, len)
#endif

#if HCI_TRACK_EN
	#define HCI_TRACK_ERR(format, ...)     write("[E][HCI] "format, ##__VA_ARGS__)
	#define HCI_TRACK_INFO(format, ...)    write("[I][HCI] "format, ##__VA_ARGS__)
	#define HCI_TRACK_WRN(format, ...)     write("[W][HCI] "format, ##__VA_ARGS__)
	#define HCI_TRACK_DATA(pData, len)     TRACK_DATA(pData, len)
#else
	#define HCI_TRACK_ERR(format, ...)
	#define HCI_TRACK_INFO(format, ...)
	#define HCI_TRACK_WRN(format, ...)
	#define HCI_TRACK_DATA(pData, len)
#endif

#if HCI_H5_TRACK_EN
	#define HCI_H5_TRACK_ERR(format, ...)     write("[E][H5_] "format, ##__VA_ARGS__)
	#define HCI_H5_TRACK_INFO(format, ...)    write("[I][H5_] "format, ##__VA_ARGS__)
	#define HCI_H5_TRACK_WRN(format, ...)     write("[W][H5_] "format, ##__VA_ARGS__)
#else
	#define HCI_H5_TRACK_ERR(format, ...)
	#define HCI_H5_TRACK_INFO(format, ...)
	#define HCI_H5_TRACK_WRN(format, ...)
#endif

#if HCI_SLIP_TRACK_EN
	#define HCI_SLIP_TRACK_ERR(format, ...)   write("[E][SLIP] "format, ##__VA_ARGS__)
	#define HCI_SLIP_TRACK_INFO(format, ...)  write("[I][SLIP] "format, ##__VA_ARGS__)
	#define HCI_SLIP_TRACK_WRN(format, ...)   write("[W][SLIP] "format, ##__VA_ARGS__)
#else
	#define HCI_SLIP_TRACK_ERR(format, ...)
	#define HCI_SLIP_TRACK_INFO(format, ...)
	#define HCI_SLIP_TRACK_WRN(format, ...)
#endif

#if HCI_TR_TRACK_EN
	#define HCI_TR_TRACK_ERR(format, ...)     write("[E][TR_] "format, ##__VA_ARGS__)
	#define HCI_TR_TRACK_INFO(format, ...)    write("[I][TR_] "format, ##__VA_ARGS__)
	#define HCI_TR_TRACK_WRN(format, ...)     write("[W][TR_] "format, ##__VA_ARGS__)
#else
	#define HCI_TR_TRACK_ERR(format, ...)
	#define HCI_TR_TRACK_INFO(format, ...)
	#define HCI_TR_TRACK_WRN(format, ...)
#endif

#if DM_TRACK_EN
	#define DM_TRACK_ERR(format, ...)     write("[E][DM_] "format, ##__VA_ARGS__)
	#define DM_TRACK_INFO(format, ...)    write("[I][DM_] "format, ##__VA_ARGS__)
	#define DM_TRACK_WRN(format, ...)     write("[W][DM_] "format, ##__VA_ARGS__)
#else
	#define DM_TRACK_ERR(format, ...)
	#define DM_TRACK_INFO(format, ...)
	#define DM_TRACK_WRN(format, ...)
#endif

#if L2C_TRACK_EN
	#define L2C_TRACK_ERR(format, ...)     write("[E][L2C] "format, ##__VA_ARGS__)
	#define L2C_TRACK_INFO(format, ...)    write("[I][L2C] "format, ##__VA_ARGS__)
	#define L2C_TRACK_WRN(format, ...)     write("[W][L2C] "format, ##__VA_ARGS__)
	#define L2C_TRACK_DATA(pData, len)     TRACK_DATA(pData, len)
#else
	#define L2C_TRACK_ERR(format, ...)
	#define L2C_TRACK_INFO(format, ...)
	#define L2C_TRACK_WRN(format, ...)
	#define L2C_TRACK_DATA(pData, len)
#endif

#if ATT_TRACK_EN
	#define ATT_TRACK_ERR(format, ...)     write("[E][ATT] "format, ##__VA_ARGS__)
	#define ATT_TRACK_INFO(format, ...)    write("[I][ATT] "format, ##__VA_ARGS__)
	#define ATT_TRACK_WRN(format, ...)     write("[W][ATT] "format, ##__VA_ARGS__)
	#define ATT_TRACK_DATA(pData, len)     TRACK_DATA(pData, len)
#else
	#define ATT_TRACK_ERR(format, ...)
	#define ATT_TRACK_INFO(format, ...)
	#define ATT_TRACK_WRN(format, ...)
    #define ATT_TRACK_DATA(pData, len)
#endif

#if GATT_TRACK_EN
	#define GATT_TRACK_ERR(format, ...)    write("[E][GATT] "format, ##__VA_ARGS__)
	#define GATT_TRACK_INFO(format, ...)   write("[I][GATT] "format, ##__VA_ARGS__)
	#define GATT_TRACK_WRN(format, ...)    write("[W][GATT] "format, ##__VA_ARGS__)
#else
	#define GATT_TRACK_ERR(format, ...)
	#define GATT_TRACK_INFO(format, ...)
	#define GATT_TRACK_WRN(format, ...)
#endif

#if SMP_TRACK_EN
	#define SMP_TRACK_ERR(format, ...)     write("[E][SMP] "format, ##__VA_ARGS__)
	#define SMP_TRACK_INFO(format, ...)    write("[I][SMP] "format, ##__VA_ARGS__)
	#define SMP_TRACK_WRN(format, ...)     write("[W][SMP] "format, ##__VA_ARGS__)
	#define SMP_TRACK_DATA(pData, len)     TRACK_DATA(pData, len)
#else
	#define SMP_TRACK_ERR(format, ...)
	#define SMP_TRACK_INFO(format, ...)
	#define SMP_TRACK_WRN(format, ...)
	#define SMP_TRACK_DATA(pData, len)
#endif

#if SDP_TRACK_EN
	#define SDP_TRACK_ERR(format, ...)     write("[E][SDP] "format, ##__VA_ARGS__)
	#define SDP_TRACK_INFO(format, ...)    write("[I][SDP] "format, ##__VA_ARGS__)
	#define SDP_TRACK_WRN(format, ...)     write("[W][SDP] "format, ##__VA_ARGS__)
	#define SDP_TRACK_DATA(pData, len)     TRACK_DATA(pData, len)
#else
	#define SDP_TRACK_ERR(format, ...)
	#define SDP_TRACK_INFO(format, ...)
	#define SDP_TRACK_WRN(format, ...)
	#define SDP_TRACK_DATA(pData, len)
#endif

#if APP_TRACK_EN
	#define APP_TRACK_ERR(format, ...)     write("[E][APP] "format, ##__VA_ARGS__)
	#define APP_TRACK_INFO(format, ...)    write("[I][APP] "format, ##__VA_ARGS__)
	#define APP_TRACK_WRN(format, ...)     write("[W][APP] "format, ##__VA_ARGS__)
	#define APP_TRACK_DAT(pData, len)      TRACK_DATA(pData, len)
#else
	#define APP_TRACK_ERR(format, ...)
	#define APP_TRACK_INFO(format, ...)
	#define APP_TRACK_WRN(format, ...)
	#define APP_TRACK_DAT(pData, len)
#endif

#if USB_TRACK_EN
	#define USB_TRACK_ERR(format, ...)     write("[E][USB] "format, ##__VA_ARGS__)
	#define USB_TRACK_INFO(format, ...)    write("[I][USB] "format, ##__VA_ARGS__)
	#define USB_TRACK_WRN(format, ...)     write("[W][USB] "format, ##__VA_ARGS__)
	#define USB_TRACK_DATA(pData, len)     TRACK_DATA(pData, len)
#else
	#define USB_TRACK_ERR(format, ...)
	#define USB_TRACK_INFO(format, ...)
	#define USB_TRACK_WRN(format, ...)
	#define USB_TRACK_DATA(pData, len)
#endif

#if MEM_TRACK_EN
	#define MEM_TRACK_ERR(format, ...)     write("[E][MEM] "format, ##__VA_ARGS__)
	#define MEM_TRACK_INFO(format, ...)    write("[I][MEM] "format, ##__VA_ARGS__)
	#define MEM_TRACK_WRN(format, ...)     write("[W][MEM] "format, ##__VA_ARGS__)
	#define MEM_TRACK_DATA(pData, len)     TRACK_DATA(pData, len)
#else
	#define MEM_TRACK_ERR(format, ...)
	#define MEM_TRACK_INFO(format, ...)
	#define MEM_TRACK_WRN(format, ...)
	#define MEM_TRACK_DATA(pData, len)
#endif

#if TRACK_MODE
	#define TRACK_DATA(pData, len)             TrackData(pData, len)
	#define TRACK_STR_DATA(pDesc, pData, len)  TrackStringData(pDesc, pData, len)
#else
	#define TRACK_DATA(pData, len)
	#define TRACK_STR_DATA(pDesc, pData, len)
#endif

/*! Timing debug system. */

#if TIMING_TRACK_EN

#ifdef TLSR8258_DK48
	#define DBG_CHN0_PIN      GPIO_PD0
	#define DBG_CHN1_PIN      GPIO_PD1
	#define DBG_CHN2_PIN      GPIO_PD6
	#define DBG_CHN3_PIN      GPIO_PD7
	#define DBG_CHN4_PIN      GPIO_PA2
    #define DBG_CHN5_PIN      GPIO_PA3
    #define DBG_CHN6_PIN      GPIO_PA4
	#define DBG_CHN7_PIN      GPIO_PB6//GPIO_PB2

	#define DBG_CHN8_PIN      GPIO_PC0
    #define DBG_CHN9_PIN      GPIO_PC1
    #define DBG_CHN10_PIN     GPIO_PC2
    #define DBG_CHN11_PIN     GPIO_PC3
    #define DBG_CHN12_PIN     GPIO_PC4
    #define DBG_CHN13_PIN     GPIO_PC5
    #define DBG_CHN14_PIN     GPIO_PC6
    #define DBG_CHN15_PIN     GPIO_PC7

	#define DBG_CHN0_HI       GPIOD->DO |= BIT(0); //GPIO_WriteBitsEx(DBG_CHN0_PIN, 1);
	#define DBG_CHN0_LO       GPIOD->DO &=~BIT(0); //GPIO_WriteBitsEx(DBG_CHN0_PIN, 0);
	#define DBG_CHN0_TOGGLE   GPIOD->DO ^= BIT(0); //GPIO_ToggleBitsEx(DBG_CHN0_PIN  );

	#define DBG_CHN1_HI       GPIOD->DO |= BIT(1); //GPIO_WriteBitsEx(DBG_CHN1_PIN, 1);
	#define DBG_CHN1_LO       GPIOD->DO &=~BIT(1); //GPIO_WriteBitsEx(DBG_CHN1_PIN, 0);
	#define DBG_CHN1_TOGGLE   GPIOD->DO ^= BIT(1); //GPIO_ToggleBitsEx(DBG_CHN1_PIN  );

	#define DBG_CHN2_HI       GPIOD->DO |= BIT(6); //GPIO_WriteBitsEx(DBG_CHN2_PIN, 1);
	#define DBG_CHN2_LO       GPIOD->DO &=~BIT(6); //GPIO_WriteBitsEx(DBG_CHN2_PIN, 0);
	#define DBG_CHN2_TOGGLE   GPIOD->DO ^= BIT(6); //GPIO_ToggleBitsEx(DBG_CHN2_PIN  );

	#define DBG_CHN3_HI       GPIOD->DO |= BIT(7); //GPIO_WriteBitsEx(DBG_CHN3_PIN, 1);
	#define DBG_CHN3_LO       GPIOD->DO &=~BIT(7); //GPIO_WriteBitsEx(DBG_CHN3_PIN, 0);
	#define DBG_CHN3_TOGGLE   GPIOD->DO ^= BIT(7); //GPIO_ToggleBitsEx(DBG_CHN3_PIN  );

	#define DBG_CHN4_HI       GPIOA->DO |= BIT(2); //GPIO_WriteBitsEx(DBG_CHN4_PIN, 1);
	#define DBG_CHN4_LO       GPIOA->DO &=~BIT(2); //GPIO_WriteBitsEx(DBG_CHN4_PIN, 0);
	#define DBG_CHN4_TOGGLE   GPIOA->DO ^= BIT(2); //GPIO_ToggleBitsEx(DBG_CHN4_PIN  );

	#define DBG_CHN5_HI       GPIOA->DO |= BIT(3); //GPIO_WriteBitsEx(DBG_CHN5_PIN, 1);
	#define DBG_CHN5_LO       GPIOA->DO &=~BIT(3); //GPIO_WriteBitsEx(DBG_CHN5_PIN, 0);
	#define DBG_CHN5_TOGGLE   GPIOA->DO ^= BIT(3); //GPIO_ToggleBitsEx(DBG_CHN5_PIN  );

	#define DBG_CHN6_HI       GPIOA->DO |= BIT(4); //GPIO_WriteBitsEx(DBG_CHN6_PIN, 1);
	#define DBG_CHN6_LO       GPIOA->DO &=~BIT(4); //GPIO_WriteBitsEx(DBG_CHN6_PIN, 0);
	#define DBG_CHN6_TOGGLE   GPIOA->DO ^= BIT(4); //GPIO_ToggleBitsEx(DBG_CHN6_PIN  );

	#define DBG_CHN7_HI       GPIOB->DO |= BIT(6); //GPIO_WriteBitsEx(DBG_CHN7_PIN, 1);
	#define DBG_CHN7_LO       GPIOB->DO &=~BIT(6); //GPIO_WriteBitsEx(DBG_CHN7_PIN, 0);
	#define DBG_CHN7_TOGGLE   GPIOB->DO ^= BIT(6); //GPIO_ToggleBitsEx(DBG_CHN7_PIN  );

	#define DBG_CHN8_HI       GPIOC->DO |= BIT(0); //GPIO_WriteBitsEx(DBG_CHN8_PIN, 1);
	#define DBG_CHN8_LO       GPIOC->DO &=~BIT(0); //GPIO_WriteBitsEx(DBG_CHN8_PIN, 0);
	#define DBG_CHN8_TOGGLE   GPIOC->DO ^= BIT(0); //GPIO_ToggleBitsEx(DBG_CHN8_PIN  );

	#define DBG_CHN9_HI       GPIOC->DO |= BIT(1); //GPIO_WriteBitsEx(DBG_CHN9_PIN, 1);
	#define DBG_CHN9_LO       GPIOC->DO &=~BIT(1); //GPIO_WriteBitsEx(DBG_CHN9_PIN, 0);
	#define DBG_CHN9_TOGGLE   GPIOC->DO ^= BIT(1); //GPIO_ToggleBitsEx(DBG_CHN9_PIN  );

	#define DBG_CHN10_HI      GPIOC->DO |= BIT(2); //GPIO_WriteBitsEx(DBG_CHN10_PIN, 1);
	#define DBG_CHN10_LO      GPIOC->DO &=~BIT(2); //GPIO_WriteBitsEx(DBG_CHN10_PIN, 0);
	#define DBG_CHN10_TOGGLE  GPIOC->DO ^= BIT(2); //GPIO_ToggleBitsEx(DBG_CHN10_PIN  );

	#define DBG_CHN11_HI      GPIOC->DO |= BIT(3); //GPIO_WriteBitsEx(DBG_CHN10_PIN, 1);
	#define DBG_CHN11_LO      GPIOC->DO &=~BIT(3); //GPIO_WriteBitsEx(DBG_CHN10_PIN, 0);
	#define DBG_CHN11_TOGGLE  GPIOC->DO ^= BIT(3); //GPIO_ToggleBitsEx(DBG_CHN10_PIN  );

	#define DBG_CHN12_HI      GPIOC->DO |= BIT(4); //GPIO_WriteBitsEx(DBG_CHN10_PIN, 1);
	#define DBG_CHN12_LO      GPIOC->DO &=~BIT(4); //GPIO_WriteBitsEx(DBG_CHN10_PIN, 0);
	#define DBG_CHN12_TOGGLE  GPIOC->DO ^= BIT(4); //GPIO_ToggleBitsEx(DBG_CHN10_PIN  );

	#define DBG_CHN13_HI      GPIOC->DO |= BIT(5); //GPIO_WriteBitsEx(DBG_CHN10_PIN, 1);
	#define DBG_CHN13_LO      GPIOC->DO &=~BIT(5); //GPIO_WriteBitsEx(DBG_CHN10_PIN, 0);
	#define DBG_CHN13_TOGGLE  GPIOC->DO ^= BIT(5); //GPIO_ToggleBitsEx(DBG_CHN10_PIN  );

	#define DBG_CHN14_HI      GPIOC->DO |= BIT(6); //GPIO_WriteBitsEx(DBG_CHN10_PIN, 1);
	#define DBG_CHN14_LO      GPIOC->DO &=~BIT(6); //GPIO_WriteBitsEx(DBG_CHN10_PIN, 0);
	#define DBG_CHN14_TOGGLE  GPIOC->DO ^= BIT(6); //GPIO_ToggleBitsEx(DBG_CHN10_PIN  );

	#define DBG_CHN15_HI      GPIOC->DO |= BIT(7); //GPIO_WriteBitsEx(DBG_CHN10_PIN, 1);
	#define DBG_CHN15_LO      GPIOC->DO &=~BIT(7); //GPIO_WriteBitsEx(DBG_CHN10_PIN, 0);
	#define DBG_CHN15_TOGGLE  GPIOC->DO ^= BIT(7); //GPIO_ToggleBitsEx(DBG_CHN10_PIN  );
#else
	#define DBG_CHN0_PIN      GPIO_PC6
	#define DBG_CHN1_PIN      GPIO_PC7
	#define DBG_CHN2_PIN      GPIO_PC3
	#define DBG_CHN3_PIN      GPIO_PC2
	#define DBG_CHN4_PIN      GPIO_PB5
    #define DBG_CHN5_PIN      GPIO_PB4
    #define DBG_CHN6_PIN      GPIO_PB3
	#define DBG_CHN7_PIN      GPIO_PB2

	#define DBG_CHN8_PIN      GPIO_PC0
    #define DBG_CHN9_PIN      GPIO_PC1
    #define DBG_CHN10_PIN     GPIO_PC2
    #define DBG_CHN11_PIN     GPIO_PC3
    #define DBG_CHN12_PIN     GPIO_PC4
    #define DBG_CHN13_PIN     GPIO_PC5
    #define DBG_CHN14_PIN     GPIO_PC6
    #define DBG_CHN15_PIN     GPIO_PC7

	#define DBG_CHN0_HI       GPIOC->DO |= BIT(6); //GPIO_WriteBitsEx(DBG_CHN0_PIN, 1);
	#define DBG_CHN0_LO       GPIOC->DO &=~BIT(6); //GPIO_WriteBitsEx(DBG_CHN0_PIN, 0);
	#define DBG_CHN0_TOGGLE   GPIOC->DO ^= BIT(6); //GPIO_ToggleBitsEx(DBG_CHN0_PIN  );

	#define DBG_CHN1_HI       GPIOC->DO |= BIT(7); //GPIO_WriteBitsEx(DBG_CHN1_PIN, 1);
	#define DBG_CHN1_LO       GPIOC->DO &=~BIT(7); //GPIO_WriteBitsEx(DBG_CHN1_PIN, 0);
	#define DBG_CHN1_TOGGLE   GPIOC->DO ^= BIT(7); //GPIO_ToggleBitsEx(DBG_CHN1_PIN  );

	#define DBG_CHN2_HI       GPIOC->DO |= BIT(3); //GPIO_WriteBitsEx(DBG_CHN2_PIN, 1);
	#define DBG_CHN2_LO       GPIOC->DO &=~BIT(3); //GPIO_WriteBitsEx(DBG_CHN2_PIN, 0);
	#define DBG_CHN2_TOGGLE   GPIOC->DO ^= BIT(3); //GPIO_ToggleBitsEx(DBG_CHN2_PIN  );

	#define DBG_CHN3_HI       GPIOC->DO |= BIT(2); //GPIO_WriteBitsEx(DBG_CHN3_PIN, 1);
	#define DBG_CHN3_LO       GPIOC->DO &=~BIT(2); //GPIO_WriteBitsEx(DBG_CHN3_PIN, 0);
	#define DBG_CHN3_TOGGLE   GPIOC->DO ^= BIT(2); //GPIO_ToggleBitsEx(DBG_CHN3_PIN  );

	#define DBG_CHN4_HI       GPIOB->DO |= BIT(5); //GPIO_WriteBitsEx(DBG_CHN4_PIN, 1);
	#define DBG_CHN4_LO       GPIOB->DO &=~BIT(5); //GPIO_WriteBitsEx(DBG_CHN4_PIN, 0);
	#define DBG_CHN4_TOGGLE   GPIOB->DO ^= BIT(5); //GPIO_ToggleBitsEx(DBG_CHN4_PIN  );

	#define DBG_CHN5_HI       GPIOB->DO |= BIT(4); //GPIO_WriteBitsEx(DBG_CHN5_PIN, 1);
	#define DBG_CHN5_LO       GPIOB->DO &=~BIT(4); //GPIO_WriteBitsEx(DBG_CHN5_PIN, 0);
	#define DBG_CHN5_TOGGLE   GPIOB->DO ^= BIT(4); //GPIO_ToggleBitsEx(DBG_CHN5_PIN  );

	#define DBG_CHN6_HI       GPIOB->DO |= BIT(3); //GPIO_WriteBitsEx(DBG_CHN6_PIN, 1);
	#define DBG_CHN6_LO       GPIOB->DO &=~BIT(3); //GPIO_WriteBitsEx(DBG_CHN6_PIN, 0);
	#define DBG_CHN6_TOGGLE   GPIOB->DO ^= BIT(3); //GPIO_ToggleBitsEx(DBG_CHN6_PIN  );

	#define DBG_CHN7_HI       GPIOB->DO |= BIT(2); //GPIO_WriteBitsEx(DBG_CHN7_PIN, 1);
	#define DBG_CHN7_LO       GPIOB->DO &=~BIT(2); //GPIO_WriteBitsEx(DBG_CHN7_PIN, 0);
	#define DBG_CHN7_TOGGLE   GPIOB->DO ^= BIT(2); //GPIO_ToggleBitsEx(DBG_CHN7_PIN  );

	#define DBG_CHN8_HI       GPIOC->DO |= BIT(0); //GPIO_WriteBitsEx(DBG_CHN8_PIN, 1);
	#define DBG_CHN8_LO       GPIOC->DO &=~BIT(0); //GPIO_WriteBitsEx(DBG_CHN8_PIN, 0);
	#define DBG_CHN8_TOGGLE   GPIOC->DO ^= BIT(0); //GPIO_ToggleBitsEx(DBG_CHN8_PIN  );

	#define DBG_CHN9_HI       GPIOC->DO |= BIT(1); //GPIO_WriteBitsEx(DBG_CHN9_PIN, 1);
	#define DBG_CHN9_LO       GPIOC->DO &=~BIT(1); //GPIO_WriteBitsEx(DBG_CHN9_PIN, 0);
	#define DBG_CHN9_TOGGLE   GPIOC->DO ^= BIT(1); //GPIO_ToggleBitsEx(DBG_CHN9_PIN  );

	#define DBG_CHN10_HI      GPIOC->DO |= BIT(2); //GPIO_WriteBitsEx(DBG_CHN10_PIN, 1);
	#define DBG_CHN10_LO      GPIOC->DO &=~BIT(2); //GPIO_WriteBitsEx(DBG_CHN10_PIN, 0);
	#define DBG_CHN10_TOGGLE  GPIOC->DO ^= BIT(2); //GPIO_ToggleBitsEx(DBG_CHN10_PIN  );

	#define DBG_CHN11_HI
	#define DBG_CHN11_LO
	#define DBG_CHN11_TOGGLE

	#define DBG_CHN12_HI
	#define DBG_CHN12_LO
	#define DBG_CHN12_TOGGLE

	#define DBG_CHN13_HI
	#define DBG_CHN13_LO
	#define DBG_CHN13_TOGGLE

	#define DBG_CHN14_HI
	#define DBG_CHN14_LO
	#define DBG_CHN14_TOGGLE

	#define DBG_CHN15_HI
	#define DBG_CHN15_LO
	#define DBG_CHN15_TOGGLE
#endif

	#define TIMING_TRACK_INIT() \
		do{\
			 uint16_t debugPinTbl[] = {\
				DBG_CHN0_PIN,  DBG_CHN1_PIN,  DBG_CHN2_PIN,  DBG_CHN3_PIN,\
				DBG_CHN4_PIN,  DBG_CHN5_PIN,  DBG_CHN6_PIN,  DBG_CHN7_PIN,\
				DBG_CHN8_PIN,  DBG_CHN9_PIN,  DBG_CHN10_PIN, DBG_CHN11_PIN,\
				DBG_CHN12_PIN, DBG_CHN13_PIN, DBG_CHN14_PIN, DBG_CHN15_PIN,\
			 };\
			for(uint32_t i=0; i<sizeof(debugPinTbl)/sizeof(debugPinTbl[0]); i++)\
			{\
				GPIO_InitEx(debugPinTbl[i], GPIO_Mode_Out);\
				GPIO_WriteBitsEx(debugPinTbl[i], false);\
			}\
		}while(0)
#else

	#define DBG_CHN0_HI
	#define DBG_CHN0_LO
	#define DBG_CHN0_TOGGLE

	#define DBG_CHN1_HI
	#define DBG_CHN1_LO
	#define DBG_CHN1_TOGGLE

	#define DBG_CHN2_HI
	#define DBG_CHN2_LO
	#define DBG_CHN2_TOGGLE

	#define DBG_CHN3_HI
	#define DBG_CHN3_LO
	#define DBG_CHN3_TOGGLE

	#define DBG_CHN4_HI
	#define DBG_CHN4_LO
	#define DBG_CHN4_TOGGLE

	#define DBG_CHN5_HI
	#define DBG_CHN5_LO
	#define DBG_CHN5_TOGGLE

	#define DBG_CHN6_HI
	#define DBG_CHN6_LO
	#define DBG_CHN6_TOGGLE

	#define DBG_CHN7_HI
	#define DBG_CHN7_LO
	#define DBG_CHN7_TOGGLE

	#define DBG_CHN8_HI
	#define DBG_CHN8_LO
	#define DBG_CHN8_TOGGLE

	#define DBG_CHN9_HI
	#define DBG_CHN9_LO
	#define DBG_CHN9_TOGGLE

	#define DBG_CHN10_HI
	#define DBG_CHN10_LO
	#define DBG_CHN10_TOGGLE

	#define DBG_CHN11_HI
	#define DBG_CHN11_LO
	#define DBG_CHN11_TOGGLE

	#define DBG_CHN12_HI
	#define DBG_CHN12_LO
	#define DBG_CHN12_TOGGLE

	#define DBG_CHN13_HI
	#define DBG_CHN13_LO
	#define DBG_CHN13_TOGGLE

	#define DBG_CHN14_HI
	#define DBG_CHN14_LO
	#define DBG_CHN14_TOGGLE

	#define DBG_CHN15_HI
	#define DBG_CHN15_LO
	#define DBG_CHN15_TOGGLE

	#define TIMING_TRACK_INIT()
#endif

void TrackInit(void);
void TrackStart(void);

void TrackPrint(const char *format, ...);
void TrackData(uint8_t *pdata, uint32_t len);
void TrackStringData(const char *txt, uint8_t *pdata, uint32_t len);

uint32_t PrintVsn(char *pStr, uint32_t size, const char *pFmt, va_list ap);
uint32_t TrackHexToString(char *pStr, uint32_t bufSize, uint8_t *pData, uint32_t len);

void TrackPrintSystemInfo(void);

void assert_failed(uint8_t exp, uint32_t errCode, char *fileName, int line);

#endif /* TRACK_H_ */
